# Clean workspace and load dependencies
rm(list = ls())
library(tidyr)
library(dplyr)
library(plotly)
library(ggplot2)
library(knitr)
library(lubridate)
# Here i defined what test subject refers to what directorty
#! should probably think about PID here later on.
# format: name, hz, skipheading
pp_info <- data.frame (
# file, hz, skiprow
bart = c("../../Logs/old/20240429_163145_bart/", 60, 7),
other = c("../../Logs/new/20240502_192335/", 60, 10)
)
LoadXsenseData <- function(nameofpp) {
dir <- nameofpp[1]
hz <- as.numeric(nameofpp[2])
skiprow <- as.numeric(nameofpp[3])
#dir <- bart
#hz <- 60
files <- list.files(path = dir, full.names = TRUE)
data <- list()
# Read CSV files of each directory
for (i in seq_along(files)) {
data[[i]] <- read.csv(files[i], header = TRUE, skip = skiprow)
}
# Ensure all dataframes have the same number of rows
min_rows <- min(sapply(data, nrow))
data <- lapply(data, function(df) {
df <- df[1:min_rows, , drop = FALSE]
return(df)
})
# Adjust time
for (i in seq_along(data)) {
rows <- nrow(data[[i]])
data[[i]]$TimeS <- ((1/hz) * (1:rows))
}
# Initialize toreturn data frame with time column
toreturn <- data.frame(time = data[[1]]$TimeS)
# Calculate absolute values
for (i in 1:length(data)) {
if ("FreeAcc_X" %in% names(data[[i]])) {
col_name <- paste0("FreeAcc_abs", i)
toreturn[[col_name]] <- sqrt(data[[i]]$FreeAcc_X^2 + data[[i]]$FreeAcc_Y^2 + data[[i]]$FreeAcc_Z^2)
}
if ("Acc_X" %in% names(data[[i]])) {
col_name <- paste0("A_abs", i)
toreturn[[col_name]] <- sqrt(data[[i]]$Acc_X^2 + data[[i]]$Acc_Y^2 + data[[i]]$Acc_Z^2)
}
if ("Gyr_X" %in% names(data[[i]])) {
col_name <- paste0("Gyr_abs", i)
toreturn[[col_name]] <- sqrt(data[[i]]$Gyr_X^2 + data[[i]]$Gyr_Y^2 + data[[i]]$Gyr_Z^2)
}
}
# Order the attributes of the dataframe
toreturn_sorted <- toreturn[, sort(names(toreturn))]
return(toreturn_sorted)
}LoadXsense
Data visualisation and management
This is the code used to visualise and manage the output of the Xsense dot IMU data. The source code can be found on my github
Load the data
Lets start by defining a function to correctly load measurements:
Note that IMU’s do not start and stop measureing at the exact same time; even after synchronization the amount of elements per IMU (the length of measurement) differs. In my implementation of temporal relaignment I assumed that the time in SampletimeFine was synchronized, and excluded first or last elements accordingly to ensure dataframes are of equal length. This eases calculation since R prefers to calculate over lists of equal length.
Visualization
lets also define some functions to visualize the data
# Some functions to visualize the acceleration and the Gyr
plot_a <- function(df) {
plot <- plot_ly(df, x = ~time, y = ~A_abs1, name = "marker1", type = "scatter", mode = "lines") %>%
add_trace(y = ~A_abs2, name = "marker 2") %>%
add_trace(y = ~A_abs3, name = "marker 3") %>%
add_trace(y = ~A_abs4, name = "marker 4") %>%
add_trace(y = ~A_abs5, name = "marker 5") %>%
layout(title = "Absolute accelerations",
xaxis = list(title = "Time"),
yaxis = list(title = "A_abs Values"))
return(plot)
}
plot_gyr <- function(df) {
plot <- plot_ly(df, x = ~time, y = ~Gyr_abs1, name = "marker1", type = "scatter", mode = "lines") %>%
add_trace(y = ~Gyr_abs2, name = "marker 2") %>%
add_trace(y = ~Gyr_abs3, name = "marker 3") %>%
add_trace(y = ~Gyr_abs4, name = "marker 4") %>%
add_trace(y = ~Gyr_abs5, name = "marker 5") %>%
layout(title = "Absolute Gyr",
xaxis = list(title = "Time"),
yaxis = list(title = "Gyr Values"))
return(plot)
}
#! Maybe include a plotting function that takes the dataframe and the attribute to plot, assuming 5 markers?Initial test
Lets load some data and see how it looks:
note: to increase performance I stored the calculated values and read them. This is faster than calculating all absolute values each time the program runs
# Storing the calculated data
# meting1 <- LoadXsenseData(pp_info[1:3,1])
# write.csv(meting1, file = "example1.csv", row.names = FALSE)
# Loading the calulated data
meting1 <- read.csv("example1.csv")
# Plot the calculated data
plot_a(meting1)